/// 底层Poll阻塞等待IO事件到来，如果没有任何IO事件，需要有立即退出的机制
/// 一个提供IO事件的通知机制, Poll可以立即从阻塞的wait中返回
/// 考虑到对性能资源要求很低, 选择inet socket，各个平台都通用
use crate::{net, Result};
use core::mem;
use core::slice;

pub(crate) struct Waker {
    pub fd: net::Fd,
}

impl Waker {
    pub fn new() -> Result<Self> {
        let fd = net::Fd::udp_socket(libc::AF_INET)?;
        let addr = net::SocketAddr::inet_from("127.0.0.1:0")?;
        fd.bind(&addr)?;

        Ok(Self { fd })
    }

    pub fn wake(&self) {
        let addr = self.fd.getsockname().unwrap();
        let msg = &self.fd as *const _ as *const u8;
        let msglen = mem::size_of_val(&self.fd);
        let buf = unsafe { slice::from_raw_parts(msg, msglen) };
        let _ = self.fd.try_sendto(buf, 0, &addr);
    }

    pub fn awaken(&self) -> bool {
        let mut fd = [-1_i32; 2];
        let buf = unsafe { slice::from_raw_parts_mut(fd.as_mut_ptr().cast::<u8>(), 4) };
        let size = self.fd.try_read(buf).unwrap_or(0);
        size == mem::size_of::<i32>() && fd[0] == self.fd.fd()
    }
}
